/**
 * Copyright phonemap.com
 *
 * Licensed under the phonemap.com License, Version 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.phonemap.com/licenses/LICENSE-1.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.phonemap;

import java.io.IOException;
import java.io.PrintWriter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.GeoPt;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.phonemap.common.Util;
import com.phonemap.models.User;

/**
 * The Class UserServlet.
 */
@SuppressWarnings("serial")
public class UserServlet extends BaseServlet {
	
	/** The Constant logger. */
	private static Logger logger = Logger.getLogger(UserServlet.class
			.getCanonicalName());

	/**
	 * Get the requested customer entities in JSON format.
	 *
	 * @param req the req
	 * @param resp the resp
	 * @throws ServletException the servlet exception
	 * @throws IOException Signals that an I/O exception has occurred.
	 */
	protected final void doGet(final HttpServletRequest req, final HttpServletResponse resp)
			throws ServletException, IOException {
//		InitEntity.insertUsers();
		super.doGet(req, resp);
		logger.log(Level.INFO, "Obtaining User listing");
		String searchFor = req.getParameter("q");
		PrintWriter out = resp.getWriter();
		Iterable<Entity> entities = null;
		if (searchFor == null || searchFor.equals("")) {
			entities = User.getAllUsers();
			out.println(Util.writeJSON(entities));
		} else {
			Entity e =  User.getUser(Long.parseLong(searchFor));
			Set<Entity> result = new HashSet<Entity>();
			result.add(e);
			out.println(Util.writeJSON(result));
		}
		return;
	}

	/**
	 * Insert the new customer.
	 *
	 * @param req the req
	 * @param resp the resp
	 * @throws ServletException the servlet exception
	 * @throws IOException Signals that an I/O exception has occurred.
	 */
	protected final void doPut(final HttpServletRequest req, final HttpServletResponse resp)
			throws ServletException, IOException {
		logger.log(Level.INFO, "Creating User");
		
		String id = req.getParameter("fid");
		String fullname = req.getParameter("fullname");
		String link = req.getParameter("link");
		Date birthday = null;
		SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
		try {
			if (req.getParameter("birthday") != null) {
				birthday = formatter.parse(req.getParameter("birthday"));
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}
		String interestedIn = req.getParameter("interested_in"); 
		String gender = req.getParameter("gender");
		String relationshipStatus = req.getParameter("relationship_status");
		String timezone = req.getParameter("timezone");
		String locale = req.getParameter("locale");
		String verified = req.getParameter("verified");
		String email = req.getParameter("email");
		String updatedTime = req.getParameter("updated_time");
		String username = req.getParameter("username");
		String password = null;
		float latitude = Float.parseFloat(req.getParameter("lat"));
		float longitude = Float.parseFloat(req.getParameter("lng"));
		String phone = req.getParameter("phone");
		if (id != null && !id.isEmpty()) {
			User.insertUser(Long.parseLong(id), fullname, link, birthday, interestedIn, 
					gender, email, relationshipStatus, timezone, 
					locale, verified, updatedTime, username, password, 
					new GeoPt(latitude, longitude), new Date(), phone);
		}
		
	}
	
	/**
	 * Update the user.
	 *
	 * @param req the req
	 * @param resp the resp
	 * @throws ServletException the servlet exception
	 * @throws IOException Signals that an I/O exception has occurred.
	 */
	protected final void doUpdate(final HttpServletRequest req, final HttpServletResponse resp)
			throws ServletException, IOException {
		logger.log(Level.INFO, "Creating User");
		
		String id = req.getParameter("id");
		String fullname = req.getParameter("fullname");
		String link = req.getParameter("link");
		Date birthday = null;
		SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
		try {
			if (req.getParameter("birthday") != null) {
				if (req.getParameter("birthday").isEmpty()) {
					birthday = formatter.parse(req.getParameter("birthday"));
				}
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}
		String interestedIn = req.getParameter("interested_in"); 
		String gender = req.getParameter("gender");
		String relationshipStatus = req.getParameter("relationship_status");
		String timezone = req.getParameter("timezone");
		String locale = req.getParameter("locale");
		String verified = req.getParameter("verified");
		String email = req.getParameter("email");
		String updatedTime = req.getParameter("updated_time");
		String username = req.getParameter("username");
		float latitude = Float.parseFloat(req.getParameter("latitude"));
		float longitude = Float.parseFloat(req.getParameter("longitude"));
		String phone = req.getParameter("phone");
		Date locatedTime = new Date();
		if (!req.getParameter("located_time").isEmpty()
				&& req.getParameter("located_time") != null
				&& !req.getParameter("located_time").equals("undefined")) {
			locatedTime = new Date(Long.parseLong(req.getParameter("located_time")));
		}
		User.updateUser(Long.parseLong(id), fullname, link, birthday, interestedIn, 
				gender, email, relationshipStatus, timezone, 
				locale, verified, updatedTime, username, 
				new GeoPt(latitude, longitude), locatedTime, phone);
	}
	
	
	/**
	 * Do update position.
	 *
	 * @param req the req
	 * @param resp the resp
	 * @throws ServletException the servlet exception
	 * @throws IOException Signals that an I/O exception has occurred.
	 */
	protected final void doUpdatePosition(final HttpServletRequest req, final HttpServletResponse resp)
			throws ServletException, IOException {
		logger.log(Level.INFO, "Creating User");
		
		String id = req.getParameter("id");
		
		float latitude = Float.parseFloat(req.getParameter("latitude"));
		float longitude = Float.parseFloat(req.getParameter("longitude"));
		Date locatedTime = new Date();
		if (!req.getParameter("located_time").isEmpty()
				&& req.getParameter("located_time") != null
				&& !req.getParameter("located_time").equals("undefined")) {
			locatedTime = new Date(Long.parseLong(req.getParameter("located_time")));
		}
		User.updatePosition(Long.parseLong(id), new GeoPt(latitude, longitude), locatedTime);
	}

	/**
	 * Delete the customer.
	 *
	 * @param req the req
	 * @param resp the resp
	 * @throws ServletException the servlet exception
	 * @throws IOException Signals that an I/O exception has occurred.
	 */
	protected final void doDelete(final HttpServletRequest req, final HttpServletResponse resp)
			throws ServletException, IOException {
		String id = req.getParameter("id");
		logger.log(Level.INFO, "Deleting User {0}", id);
		Key key = KeyFactory.createKey("User", Long.parseLong(id));
		try {
			// CASCADE_ON_DELETE
			Iterable<Entity> entities = Util.listChildKeys("Position", key);
			final List<Key> positionkeys = new ArrayList<Key>();
			for (Entity e : entities) {
				positionkeys.add(e.getKey());

			}
			Util.deleteEntity(positionkeys);
			Util.deleteFromCache(key);
			Util.deleteEntity(key);
		} catch (Exception e) {
			String msg = Util.getErrorResponse(e);
			resp.getWriter().print(msg);
		}
	}

	/**
	 * Redirect the call to doDelete or doPut method.
	 *
	 * @param req the req
	 * @param resp the resp
	 * @throws ServletException the servlet exception
	 * @throws IOException Signals that an I/O exception has occurred.
	 */
	protected final void doPost(final HttpServletRequest req, final HttpServletResponse resp)
			throws ServletException, IOException {
		String action = req.getParameter("action");
		if (action.equalsIgnoreCase("delete")) {
			doDelete(req, resp);
			return;
		} else if (action.equalsIgnoreCase("put")) {
			doPut(req, resp);
			return;
		} else if (action.equalsIgnoreCase("update")) {
			doUpdate(req, resp);
			return;
		} else if (action.equalsIgnoreCase("insert")) {
			doInsert(req, resp);
			return;
		} else if (action.equalsIgnoreCase("updateposition")) {
			doUpdatePosition(req, resp);
			return;
		}
	}
	
	/**
	 * Do insert.
	 *
	 * @param req the req
	 * @param resp the resp
	 * @throws ServletException the servlet exception
	 * @throws IOException Signals that an I/O exception has occurred.
	 */
	protected final void doInsert(final HttpServletRequest req, final HttpServletResponse resp)
			throws ServletException, IOException {
		logger.log(Level.INFO, "Creating User");
		
		String id = req.getParameter("id");
		String fullname = req.getParameter("fullname");
		String link = req.getParameter("link");
		Date birthday = null;
		SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
		try {
			if (!req.getParameter("birthday").isEmpty()
					&& req.getParameter("birthday") != null
					&& !req.getParameter("birthday").equals("undefined")) {
				birthday = formatter.parse(req.getParameter("birthday"));
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}
		String interestedIn = req.getParameter("interested_in"); 
		String gender = req.getParameter("gender");
		String relationshipStatus = req.getParameter("relationship_status");
		String timezone = req.getParameter("timezone");
		String locale = req.getParameter("locale");
		String verified = req.getParameter("verified");
		String email = req.getParameter("email");
		String updatedTime = req.getParameter("updated_time");
		String username = req.getParameter("username");
		String password = null;
		String phone = req.getParameter("phone");
		float latitude = Float.parseFloat(req.getParameter("latitude"));
		float longitude = Float.parseFloat(req.getParameter("longitude"));
		Date locatedTime = new Date();
		if (!req.getParameter("located_time").isEmpty()
				&& req.getParameter("located_time") != null
				&& !req.getParameter("located_time").equals("undefined")) {
			locatedTime = new Date(Long.parseLong(req.getParameter("located_time")));
		}
		User.insertUser(Long.parseLong(id), fullname, link, birthday, interestedIn, 
				gender, email, relationshipStatus, timezone, 
				locale, verified, updatedTime, username, password, 
				new GeoPt(latitude, longitude), locatedTime, phone);
	}
}
